/*
Copyright 2010 Jacek Karczmarczyk

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

function GoogleMapsTraceRoute(mapElement, inputLat, inputLng) {
	this.map = null;
	this.window = new google.maps.InfoWindow();
	this.adminMarker = null;

	/**
	 * Displays map with a route
	 * 
	 */
	this.initialize = function (route, pointsVisible, color, showRoute) {
		this._initializeMap(0, 0, this._showRoute, [route, pointsVisible, color, showRoute]);
	};

	/**
	 * Sets the map center to the adminMarker
	 *
	 */
	this.gotoMarker = function () {
		if (!this.map || !this.adminMarker) return;
		this.map.setCenter(this.adminMarker.getPosition());
	};

	/**
	 * Displays maps and sets the click handler to function setting longitute and latitude on the location form
	 * 
	 */
	this.initializeAdmin = function (center) {
		var that = this, lat = center && center.lat && center.lat(), lng = center && center.lng && center.lng();

		if (!lat && !lng && navigator.geolocation) {
			navigator.geolocation.getCurrentPosition(function (position) {
				if (!that.map) {
					that._initializeMap(position.coords.latitude, position.coords.longitude, that._initializeCallback, [new google.maps.LatLng(position.coords.latitude, position.coords.longitude)]);
				}
			});
		}
		else {
			this._initializeMap(lat, lng, this._initializeCallback, [center]);
		}
	};

	/**
	 * Set the map center to the marker position
	 *
	 */
	this.adminFindLocation = function (locationName) {
		var that = this;
		(new google.maps.Geocoder()).geocode( {'address': locationName}, function(results, status) {
			if (that.map && status == google.maps.GeocoderStatus.OK) {
				that.map.setCenter(results[0].geometry.location);
				that._setMarkerPosition(results[0].geometry.location);
			} else if (status != google.maps.GeocoderStatus.OK) {
				alert("Geocode was not successful for the following reason: " + status);
			}
		});
	}


	/**
	 * Callback called after map is initiatlized
	 *
	 */
	this._initializeCallback = function (latLng) {
		var that = this;
		if (inputLat && inputLng && document.getElementById(inputLat) && document.getElementById(inputLng)) {
			google.maps.event.addListener(this.map, 'click', function (event) {
				that._setMarkerPosition(event.latLng);
			});
		}

		this.adminMarker = new google.maps.Marker({ map: this.map, draggable: true });
		this._setMarkerPosition(latLng);
		google.maps.event.addListener(this.adminMarker, 'dragend', function () {
			that._setMarkerPosition(this.getPosition());
		});

	};


	/**
	 * Sets the marker position and the value of location input fields
	 *
	 */
	this._setMarkerPosition = function (latLng) {
		document.getElementById(inputLat).value = latLng.lat();
		document.getElementById(inputLng).value = latLng.lng();
		this.adminMarker.setPosition(latLng);
	}


	/**
	 * Initializes the map and calls the callback
	 *
	 */
	this._initializeMap = function (centerLat, centerLon, callback, args) {
		this.map = new google.maps.Map(mapElement, {
			zoom: 10,
			center: new google.maps.LatLng(centerLat, centerLon),
			mapTypeId: google.maps.MapTypeId.HYBRID
		});
		
		callback && callback.apply(this, args);
	};


	/**
	 * Shows the markers, route line and set the zoom so that all last pointsVisible markers are visible
	 * route = [lat, lng, title, description, detached]
	 *
	 */
	this._showRoute = function (route, pointsVisible, color, showRoute) {
		var i, routePoints = [], bounds = new google.maps.LatLngBounds(), marker, latLng;

		if (!route.length) {
			return;
		}

		for(i = 0; i < route.length; i++) {
			latLng = new google.maps.LatLng(route[i][0], route[i][1]);
			if (route[i][4] == 'yes') {
				marker = new google.maps.Marker({
					position: latLng,
					map: this.map,
					title: "" + (i+1) + "/" + route.length + ": " + route[i][2],
					zIndex: i
				});
			}

			if (route[i][4] == 'yes' || route[i][4] == 'hid') {
				routePoints.push(latLng);
			}

			if (!pointsVisible || i+pointsVisible >= route.length) {
				bounds.extend(latLng);
			}

			marker && google.maps.event.addListener(marker, 'click', (function (window, marker, description) {
				return function () {
					window.setPosition(marker.getPosition());
					window.setContent('<h3 class="gmtr_infowindow_title">'+marker.getTitle()+'</h3><div>'+description+'</div>');
					window.open(marker.getMap());
				};
			}(this.window, marker, route[i][3])));
		}


		showRoute && (new google.maps.Polyline({
			path: routePoints,
			strokeColor: color,
			strokeOpacity: 0.7,
			strokeWeight: 5
		})).setMap(this.map);
		this.map.setCenter(new google.maps.LatLng(route[route.length-1][0], route[route.length-1][1]))
		this.map.fitBounds(bounds);
	};
}
